package custom;

import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

public class Promise{
    // 执行状态
    private  static final int PENDING=1;
    private  static final int  FULFILLED =2;
    private  static final int  REJECTED=3;
    private volatile int  status = PENDING; // 状态默认为pending等待
    private static final Object lock=new Object();


    private Object value; // 成功之后的值
    private Object reason; // 失败之后的原因

//    successCallback = []; // 成功的回调函数
//    failCallback = []; // 失败的回调函数

    public Promise(BiConsumer<Consumer,Consumer> executor){
        try {
            executor.accept(this.resolve,this.reject);
        }catch (Exception e){
            reject.accept(e);
        }
    }

    private final Consumer resolve =(V)->{

        if (status!=PENDING) return; // 当状态不是等待，直接返回
        synchronized (lock){
            if (status!=PENDING) return;
            this.status = FULFILLED; // 将状态改为成功
            this.value = V; // 将成功的值传递
            lock.notifyAll();
        }

        // todo 执行成功回调函数
    };

    private final Consumer reject =(V)->{

        if (status!=PENDING) return; // 当状态不是等待，直接返回
        synchronized (lock){
            if (status!=PENDING) return;
            this.status = REJECTED; // 将状态改为成功
            this.reason = V; // 将成功的值传递
            lock.notifyAll();
        }

        // todo 执行成功回调函数
    };

    /**
     *
     * @param successCallback 成功回调函数
     * @param failCallback 失败调用函数
     * @return
     */
    public Promise then(Function successCallback,Function failCallback){
        System.out.println(12325);
        synchronized (lock){
            while (status==PENDING){
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        if (successCallback!=null&&status==FULFILLED){
            successCallback.apply(value);
        }
        if (failCallback!=null&&status==REJECTED){
            failCallback.apply(reason);
        }
        return this;
    }


}
